import javax.vecmath.*;
import javax.media.j3d.*;

import com.sun.j3d.loaders.Scene;
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.image.TextureLoader;
import com.sun.j3d.utils.universe.*;
import com.sun.j3d.utils.behaviors.vp.*;

import javax.swing.JFrame;

import org.jdesktop.j3d.loaders.vrml97.VrmlLoader;

import java.awt.Label;


/**
* Beispiel fuer eine dreidimensionale Szene, die aus elementaren
* Objekten zusammengesetzt wurde sowie Texturen und Licht enthält
*
* @author Juergen Kampmann nach einem Beispiel von Frank Klawonn
* Letzte Aenderung 01.04.2011
*/
public class r2d2 extends JFrame
{	  
	  static protected Label label; // Fuer Text an Fensterunterkante
	  protected BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
	  //Der Canvas, auf den gezeichnet wird.
	  public Canvas3D myCanvas3D; // Betrachtungsuniversum


	  public String WRL_File = null;
	  public Scene scene = null;
	  VrmlLoader		loader;
	  BranchGroup		sceneGroup;
	  TransformGroup	examineGroup;
	  

	  public r2d2()
	  {
	    //Mechanismus zum Schliessen des Fensters und beenden des Programms
	    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


	    //Standardeinstellung fuer das Betrachteruniversum
	    // das simpleUniverse erhält bevorzugte config
	    myCanvas3D = new Canvas3D(SimpleUniverse.getPreferredConfiguration());


	    //Aufbau des SimpleUniverse:
	    //Zuerst Erzeugen zusammen mit dem Canvas
	    SimpleUniverse simpUniv = new SimpleUniverse(myCanvas3D);


	    //Standardpositionierung des Betrachters
	    simpUniv.getViewingPlatform().setNominalViewingTransform();


	    //Die Szene wird in dieser Methode erzeugt.
	    createSceneGraph(simpUniv);


	    //Hinzufuegen von Licht (probieren Sie Varianten mit diesem Licht und ohne!
	    //Zeile einfach auskommentieren
	    addLight(simpUniv);


	    //Hierdurch kann man mit der Maus den Betrachterstandpunkt veraendern
	    OrbitBehavior ob = new OrbitBehavior(myCanvas3D);
	    ob.setSchedulingBounds(new BoundingSphere(new Point3d(0.0,0.0,0.0),Double.MAX_VALUE));
	    simpUniv.getViewingPlatform().setViewPlatformBehavior(ob);

	    //Setting users control
	    View view = simpUniv.getViewer().getView();
		view.setTransparencySortingPolicy(View.TRANSPARENCY_SORT_GEOMETRY);

	    

	    //Darstellung des Canvas/Fensters:
	    setTitle("R2D2 mit Texture und Objekt aus wrl-Datei");
	    setSize(1000,750);
	    getContentPane().add("Center", myCanvas3D);
	    setVisible(true);

	  }

	  public static void main(String[] args)
	  {
	     r2d2 staticScene = new r2d2();
	     label = new Label("Kameraeinstellung: Linke Maustaste -> " +
	     		           " Rotation, rechte Maustaste-> Translation, " +
  		                   " Alt+linke Maustaste-> Zoom");
         staticScene.add("South", label);
	  }



	  //In dieser Methode werden die Objekte der Szene aufgebaut und dem
	  //SimpleUniverse su hinzugefuegt.
	  public void createSceneGraph(SimpleUniverse su) // bekommt simpleUniverse übergeben
	  {
		  //********************************** 1. Teil ********************

		 /*
		  * Die Plattform, auf der R2D2 steht.
		  * Die Texture ist eine Wiese.
		  * Der Boden ist eine einzelne Transformationsgruppe.
		  */


	    //Halbe Seitenlaenge des Wuerfels, der die Plattform darstellt.
	    float plattformSeitenlaenge = 0.4f;
	    float plattformDicke = 0.025f;

	    //Erzeugung der Plattform als Wuerfel
	    Box platform = new Box(
	    		plattformSeitenlaenge,
	    		plattformDicke,
	    		plattformSeitenlaenge, 
	    		Box.GENERATE_TEXTURE_COORDS + Box.GENERATE_NORMALS, //Texturkoordinaten und Normalenvektoren erzeugen
	    		texture("wiese256.jpg", 256, 256));
	    platform.setUserData(new String("Plattform"));
	    
	    //Die Transformationsgruppe der Plattform
	    TransformGroup tgPlatform = new TransformGroup();
	    tgPlatform.addChild(platform);

	    /*
	     * Der Rumpf/Kopf des R2D2 wird als Transformationsgruppe implementiert,
	     * da der Rumpf/Kopf etwas nach hinten geneigt wird
	     */
	    
	    //Beschreibung des Rumpfes in Form eines Quaders
	    float rumpfHoehe = 0.225f;
	    float rumpfDicke = 0.1f;

	    //Erzeugung des Rumpfes als Zylinder
	    Cylinder rumpf = new Cylinder(
	    		rumpfDicke,
	    		rumpfHoehe,
	    		Cylinder.GENERATE_TEXTURE_COORDS + Cylinder.GENERATE_NORMALS,
	    		texture("r2d2128.jpg", 128, 128));
	    rumpf.setUserData(new String("Rumpf"));

	    Transform3D tfRumpf = new Transform3D();
	    
	    //Der Rumpf wird nach oben verschoben
	    tfRumpf.setTranslation(new Vector3d(
	    		0,
	    		(plattformDicke)+(rumpfHoehe-0.075f),
	    		0));
	    
	    TransformGroup tgRumpf = new TransformGroup(tfRumpf);
	    tgRumpf.addChild(rumpf);
	    
	    /*
	     * Kopf und Auge bilder eine Transformationsgruppe
	     */
	    
	    //Beschreibung des Kopfes in Form einer Kugel
	    float kopfRadius = 0.0975f;
	    
	   //Erzeugung des Kopfes als Kugel
	    Sphere kopf = new Sphere(
	    		kopfRadius,
	    		Sphere.GENERATE_TEXTURE_COORDS + Sphere.GENERATE_NORMALS,
	    		30,texture("silber.jpg", 128, 128));
	    kopf.setUserData(new String("Kopf"));
	    
	    Transform3D tfKopf = new Transform3D();
	    
	    //Der Kopf wird nach oben verschoben
	    tfKopf.setTranslation(new Vector3d(
	    		0,
	    		(plattformDicke)+(rumpfHoehe-0.075f)+(kopfRadius),
	    		0));
	    
	    TransformGroup tgKopf = new TransformGroup(tfKopf);
	    tgKopf.addChild(kopf);
	    
	    //Beschreibung des Auges des Kopfes
	    float augeRadius = 0.0125f;
	    
	    Sphere auge = new Sphere(
	    		augeRadius,
	    		Sphere.GENERATE_TEXTURE_COORDS + Sphere.GENERATE_NORMALS,
	    		texture("gold.jpg", 128, 128));
	    auge.setUserData(new String("Auge"));
	    
	    Transform3D tfauge = new Transform3D();
	    
	    //Das Auge wird nach oben verschoben
	    tfauge.setTranslation(new Vector3d(
	    		kopfRadius-0.005f,
	    		(plattformDicke)+(rumpfHoehe-0.075f)+(kopfRadius),
	    		0));
	    
	    TransformGroup tgAuge = new TransformGroup(tfauge);
	    tgAuge.addChild(auge);
	    
	    //Das Auge sitzt auf dem Kopf - der Kopf wird nach oben gedreht
	    Transform3D tfkopgKomplete = new Transform3D();
	    tfkopgKomplete.setTranslation(new Vector3f(
	    		0.07f,
	    		0.025f,
	    		0.0f));
	    
	    Transform3D rotationX_KK = new Transform3D();
	    Transform3D rotationY_KK = new Transform3D();
	    Transform3D rotationZ_KK = new Transform3D();

	    //Der Rumpf wird ein wenig nach hinten geklappt
	    rotationX_KK.rotX(0);
	    rotationY_KK.rotY(0);
	    rotationZ_KK.rotZ(Math.PI/12);
	    
	    tfkopgKomplete.mul(rotationX_KK);
	    tfkopgKomplete.mul(rotationY_KK);
	    tfkopgKomplete.mul(rotationZ_KK);

	    //Die Transformationsgruppe fuer die Einheit Kopf und Auge
	    TransformGroup tgkopgKomplete = new TransformGroup(tfkopgKomplete);
	    tgkopgKomplete.addChild(tgKopf);
	    tgkopgKomplete.addChild(tgAuge);
	    
	    /*
	     * Der komplette Kopf und der Rumpf bilden eine Transformationsgruppe
	     * und werden als Ganzes leicht nach hinten gekippt.
	     */

	  //Das Auge sitzt auf dem Kopf - der Kopf wird nach oben gedreht
	    Transform3D tfRumpfKomplete = new Transform3D();
	    tfRumpfKomplete.setTranslation(new Vector3f(
	    		0.05f,
	    		0.025f,
	    		0.0f));
	    
	    Transform3D rotationX_RK = new Transform3D();
	    Transform3D rotationY_RK = new Transform3D();
	    Transform3D rotationZ_RK = new Transform3D();

	    //Der Rumpf wird ein wenig nach hinten geklappt
	    rotationX_RK.rotX(0);
	    rotationY_RK.rotY(0);
	    rotationZ_RK.rotZ(Math.PI/25);
	    
	    tfRumpfKomplete.mul(rotationX_RK);
	    tfRumpfKomplete.mul(rotationY_RK);
	    tfRumpfKomplete.mul(rotationZ_RK);

	    //Die Transformationsgruppe fuer die Einheit Kopf und Rumpf
	    TransformGroup tgRumpfKomplete = new TransformGroup(tfRumpfKomplete);
	    tgRumpfKomplete.addChild(tgkopgKomplete);
	    tgRumpfKomplete.addChild(tgRumpf);
	    
	    /*
	     * Das Bein des R2D2 als Transformationsgruppe
	     * Einzelbestandteile:
	     * 		- Schultergelenk
	     * 		- Beine
	     * 		- Fuesse
	     */
	    
	    /*
	     * Schultergelenk
	     */
	    
	    //Maße Schultergelenk - als Zylinder
	    float SchultergelenkHoehe = 0.275f;
	    float SchultergelenkDicke = 0.015f;
	    
	    //Erzeugung des Schultergelenks als Zylinder
	    Cylinder Schultergelenk = new Cylinder(
	    		SchultergelenkDicke,
	    		SchultergelenkHoehe,
	    		Cylinder.GENERATE_TEXTURE_COORDS + Cylinder.GENERATE_NORMALS,
	    		texture("gold.jpg", 128, 128));
	    Schultergelenk.setUserData(new String("Schultergelenk"));

	    Transform3D ftSchultergelenk = new Transform3D();
	    
	    //Das Schultergelenk wird nach oben verschoben
	    ftSchultergelenk.setTranslation(new Vector3d(
	    		0.01f,
	    		rumpfHoehe+0.05f,
	    		0));
	    
	    Transform3D rotationX_SG = new Transform3D();
	    Transform3D rotationY_SG = new Transform3D();
	    Transform3D rotationZ_SG = new Transform3D();

	    //Das Schultergelenk wird ein wenig nach hinten geklappt
	    rotationX_SG.rotX(Math.PI/2);
	    rotationY_SG.rotY(0);
	    rotationZ_SG.rotZ(0);
	    
	    ftSchultergelenk.mul(rotationX_SG);
	    ftSchultergelenk.mul(rotationY_SG);
	    ftSchultergelenk.mul(rotationZ_SG);
	    
	    TransformGroup tgSchultergelenk = new TransformGroup(ftSchultergelenk);
	    tgSchultergelenk.addChild(Schultergelenk);
	    
	    /*
	     * Bein Links
	     */
	    
	    //Maße Bein - als Zylinder
	    float BeinHoehe = 0.225f;
	    float BeinDicke = 0.0125f;
	    
	    //Erzeugung des BeinLinks als Zylinder
	    Cylinder BeinLinks = new Cylinder(
	    		BeinDicke,
	    		BeinHoehe,
	    		Cylinder.GENERATE_TEXTURE_COORDS + Cylinder.GENERATE_NORMALS,
	    		texture("silber.jpg", 128, 128));
	    BeinLinks.setUserData(new String("linkes Bein"));

	    Transform3D ftBeinLinks = new Transform3D();
	    
	    //Das linke Bein wird nach oben verschoben
	    ftBeinLinks.setTranslation(new Vector3d(
	    		(rumpfDicke/2)-0.04f,
	    		rumpfHoehe-0.075,
	    		0.12f));
	    
	    TransformGroup tgBeinLinks = new TransformGroup(ftBeinLinks);
	    tgBeinLinks.addChild(BeinLinks);
	    
	    /*
	     * Bein Rechts
	     */
	    
	    //Erzeugung des BeinRechts als Zylinder
	    Cylinder BeinRechts = new Cylinder(
	    		BeinDicke,
	    		BeinHoehe,
	    		Cylinder.GENERATE_TEXTURE_COORDS + Cylinder.GENERATE_NORMALS,
	    		texture("silber.jpg", 128, 128));
	    BeinRechts.setUserData(new String("rechtes Bein"));
	    

	    Transform3D ftBeinRechts = new Transform3D();
	    
	    //Das rechte Bein wird nach oben verschoben
	    ftBeinRechts.setTranslation(new Vector3d(
	    		(rumpfDicke/2)-0.04f,
	    		rumpfHoehe-0.075,
	    		-0.12f));
	   
	    TransformGroup tgBeinRechts = new TransformGroup(ftBeinRechts);
	    tgBeinRechts.addChild(BeinRechts);
	    
	    /*
	     * Fuss Links
	     */
	    
	    //Halbe Seitenlaenge des Fusses, der die Plattform darstellt.
	    float fussSeitenlaenge = 0.05f;
	    float fussformDicke = 0.008f;

	    //Erzeugung des Fusses als Wuerfel
	    Box fussLinks = new Box(
	    		fussSeitenlaenge,
	    		fussformDicke,
	    		fussSeitenlaenge/2, 
	    		Box.GENERATE_TEXTURE_COORDS + Box.GENERATE_NORMALS,
	    		texture("stahl.jpg", 64, 64));
	    fussLinks.setUserData(new String("linker Fuß"));
	    
	    Transform3D ftFussLinks = new Transform3D();
	    
	    //Der Fuss wird nach oben verschoben
	    ftFussLinks.setTranslation(new Vector3d(
	    		0,
	    		plattformDicke+fussformDicke,
	    		rumpfDicke+0.02f));

	    //Die Transformationsgruppe des linken Fusses
	    TransformGroup tgFussLinks = new TransformGroup(ftFussLinks);
	    tgFussLinks.addChild(fussLinks);
	    
	    
	    /*
	     * Kegel fuer Fuss Links
	     */
	    
	    //Hoehe der Kegels
	    float fussKegelHoehe = 0.1f;
	    float fussKegelBreite = 0.02f;

	    //Erzeugung des Fusskegels als goldener Kegel
	    Cone fussLinksKegel = new Cone(
	    		fussKegelBreite,
	    		fussKegelHoehe,
	    		Cone.GENERATE_TEXTURE_COORDS + Cone.GENERATE_NORMALS,
	    		texture("gold.jpg", 128, 128));

	    Transform3D ftfussLinksKegel = new Transform3D();
	    
	    //Der linke Fusskegel wird nach oben verschoben
	    ftfussLinksKegel.setTranslation(new Vector3d(
	    		0,
	    		(plattformDicke)+(fussKegelHoehe/2),
	    		-(rumpfDicke)-0.02f));

	    //Die Transformationsgruppe des linken Fusskegels.
	    TransformGroup tgfussLinksKegel = new TransformGroup(ftfussLinksKegel);
	    tgfussLinksKegel.addChild(fussLinksKegel);
	    
	    /*
	     * Fuss Rechts
	     */
	    
	    //Erzeugung des Fusses als Wuerfel
	    Box fussRechts = new Box(
	    		fussSeitenlaenge,
	    		fussformDicke,
	    		fussSeitenlaenge/2, 
	    		Box.GENERATE_TEXTURE_COORDS + Box.GENERATE_NORMALS,
	    		texture("stahl.jpg", 64, 64));
	    fussRechts.setUserData(new String("rechter Fuß"));
	    
	    Transform3D ftFussRechts = new Transform3D();
	    
	    //Der Fuss wird nach oben verschoben
	    ftFussRechts.setTranslation(new Vector3d(
	    		0,
	    		plattformDicke+fussformDicke,
	    		-(rumpfDicke+0.02f)));

	    //Die Transformationsgruppe des rechten Fusses
	    TransformGroup fgFussRechts = new TransformGroup(ftFussRechts);
	    fgFussRechts.addChild(fussRechts);
	    
	    /*
	     * Kegel fuer Fuss Rechts
	     */

	    //Erzeugung des Fusskegels als goldener Kegel
	    Cone fussRechtsKegel = new Cone(
	    		fussKegelBreite,
	    		fussKegelHoehe,
	    		Cone.GENERATE_TEXTURE_COORDS + Cone.GENERATE_NORMALS,
	    		texture("gold.jpg", 128, 128));

	    Transform3D ftFussRechtsKegel = new Transform3D();
	    
	    //Der rechte Fusskegel wird nach oben verschoben
	    ftFussRechtsKegel.setTranslation(new Vector3d(
	    		0,
	    		(plattformDicke)+(fussKegelHoehe/2),
	    		(rumpfDicke)+0.02f));

	    //Die Transformationsgruppe des rechten Fusskegels.
	    TransformGroup tgFussRechtsKegel = new TransformGroup(ftFussRechtsKegel);
	    tgFussRechtsKegel.addChild(fussRechtsKegel);
	    
	    /*
	     * Fuss Mitte
	     */
	    
	    //Hoehe der Fusses
	    float fussHoehe = 0.1f;
	    float fussBreite = 0.04f;

	    //Erzeugung des Fusses als silberner Kegel
	    Cone fussMitte = new Cone(
	    		fussBreite,
	    		fussHoehe,
	    		Cone.GENERATE_TEXTURE_COORDS + Cone.GENERATE_NORMALS,
	    		texture("silber.jpg", 128, 128));
	    fussMitte.setUserData(new String("Fuß mitte"));

	    Transform3D ftFussMitte = new Transform3D();
	    
	    //Der Mittelfuss wird nach oben verschoben
	    ftFussMitte.setTranslation(new Vector3d(
	    		-(rumpfDicke/2)+0.025f,
	    		(plattformDicke)+(fussHoehe/2),
	    		0));

	    //Die Transformationsgruppe des Mittelfusses.
	    TransformGroup fgFussMitte = new TransformGroup(ftFussMitte);
	    fgFussMitte.addChild(fussMitte);
	

	//*** Der R2D2 und die Plattform bilden eine Transformatinsgruppe, ***
	//*** da sie gemeinsam in der Szene positioniert werden sollen.            ***

	    //Die Transformation zur Positionierung der Einheit
	    //R2D2 auf Plattform in der Szene.
	    Transform3D tfR2D2Plattform = new Transform3D();
	    tfR2D2Plattform.setTranslation(new Vector3f(0.0f,-0.1f,0.0f));
	    //tfR2D2Plattform.rotY(Math.PI / 4.0d); // wird zur ersten Ansicht ein wenig gedreht
	    Transform3D tfR2D2Plattform_kipp = new Transform3D(); // dann noch gekippt
	    //tfR2D2Plattform_kipp.rotX(Math.PI / 12.0d);
	    //tfR2D2Plattform.mul(tfR2D2Plattform_kipp);

	    //Die Transformationsgruppe fuer die Einheit R2D2 auf Plattform
	    TransformGroup tgR2D2Plattform = new TransformGroup(tfR2D2Plattform);
	    tgR2D2Plattform.addChild(tgPlatform);
	    tgR2D2Plattform.addChild(tgRumpfKomplete);
	    tgR2D2Plattform.addChild(tgSchultergelenk);
	    tgR2D2Plattform.addChild(tgBeinLinks);
	    tgR2D2Plattform.addChild(tgfussLinksKegel);
	    tgR2D2Plattform.addChild(tgBeinRechts);
	    tgR2D2Plattform.addChild(tgFussRechtsKegel);
	    tgR2D2Plattform.addChild(tgFussLinks);
	    tgR2D2Plattform.addChild(fgFussRechts);
	    tgR2D2Plattform.addChild(fgFussMitte);
	     
	    
	//*** Die Wurzel des Graphen, der die Szene enthaelt. ***
	    BranchGroup theScene = new BranchGroup();

	    //Fuege den R2D2 und die Plattform zur Szene.
	    theScene.addChild(tgR2D2Plattform);

	    //********************************** 2. Teil ********************
        //Lade ein Objekt aus einer wrl-Datei
	    WRL_File="tippkick_spieler.wrl";
				
	    // Jetzt wird die angegebene WRL-Datei gelesen, sie muss sich im gleichen
		// Verzeichnis befinden wie die Class-Dateien

		loader = new VrmlLoader();
		System.out.println("Die Datei solls sein: "+WRL_File);
		try{
				scene = loader.load(WRL_File);
			} catch (Exception e){

			  System.out.println("FEHLER!!! Scene nicht gefunden:");
			}
				
		if (sceneGroup != null) {
			    sceneGroup.detach();
			}

		// die in eine "Scene" geladene WRL-Datei
		// wird an die TransformGroup "examineGroup" gehaengt und erbt damit
		// die der TG zugewiesenen Eigenschaften...

		if (scene != null) {
			System.out.println("Jetzt hamwas...... ");
		    sceneGroup = scene.getSceneGroup();
		    sceneGroup.setCapability(BranchGroup.ALLOW_DETACH);
		    sceneGroup.setCapability(BranchGroup.ALLOW_BOUNDS_READ);
		    // SceneGroup an die TG haengen
    	    Transform3D tfsceneGroup = new Transform3D();
    	    // Skalieren des geladenen externen Objekts
		    tfsceneGroup.setScale(0.0005d);
		    // Verschieben des geladenen externen Objekts
		    tfsceneGroup.setTranslation(new Vector3f(0.0f,-0.072f,-0.275f));
				    
			// diese TG erlaubt "Child"-Elemente, sich an die Gruppe
			// anzuhaengen und deren Inhalte zu Lesen
			examineGroup = new TransformGroup();
			examineGroup.setCapability(TransformGroup.ALLOW_CHILDREN_EXTEND);
			examineGroup.setCapability(TransformGroup.ALLOW_CHILDREN_READ);
			examineGroup.setCapability(TransformGroup.ALLOW_CHILDREN_WRITE);
			examineGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
			examineGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
					
		    examineGroup.setTransform(tfsceneGroup);
		    examineGroup.addChild(sceneGroup);

    		} else {
				System.out.println("nix da... ");
				}
		
		//Fuege das Objekt aus der wrl-Datei zur Szene.
		theScene.addChild(examineGroup);

	    //Die folgenden drei Zeilen erzeugen einen weißen Hintergrund.
	    Background bg = new Background(new Color3f(0.8f,0.8f,0.8f));
	    BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0),Double.MAX_VALUE);
	    bg.setApplicationBounds(bounds);
	    theScene.addChild(bg);

	    // Hier wird das Picking hinzugefŸgt
	    SimplePickRightBehaviour simplePick = 
	    	new SimplePickRightBehaviour(myCanvas3D, theScene, new BoundingSphere());
	    theScene.addChild(simplePick);

	
	    theScene.compile();

	    //Hinzufuegen der Szene
	    su.addBranchGraph(theScene);
	    
	  }

	  /**
	  * Erzeugt eine Standardoberflaechenstruktur in einer gewuenschten Farbe
	  *
	  * @param app      Die Appearance, mit der die Oberflaeche belegt werden soll
	  * @param col      Die gewuenschte Farbe
	  */
	  public static void setToMyDefaultAppearance(Appearance app, Color3f col)
	  {
	    app.setMaterial(new Material(col,col,col,col,150.0f));
	  }
	  
	  /**
	   * Erzeuge iene Standardoberflächentextur in der gewünschten Textur
	   * @param s		Die gewünschte Textur
	   * @param breite	Breite der Textur
	   * @param hoehe	Hoehe der Textur
	   * @return		appear
	   */
	  public Appearance texture(String s, int breite, int hoehe) {
	        TextureLoader loader = new TextureLoader(s, this);
	        ImageComponent2D image = loader.getImage();
	        Texture2D texture = new Texture2D();
	        int form  = texture.getFormat();
	        int base = texture.getMipMapMode();
	        texture = new Texture2D(base,form,breite,hoehe);
	        texture.setImage(0, image);
	        Appearance appear = new Appearance();
	        appear.setTexture(texture);
	        TextureAttributes texat = new TextureAttributes( 
	        		TextureAttributes.COMBINE_INTERPOLATE,new Transform3D(),
	        		new Color4f(),
	        		TextureAttributes.NICEST );
	        appear.setTextureAttributes(texat);
	        appear.setMaterial(new Material());
	        return(appear);
	  }

	  /**
		  * Erzeugt eine "Standardbeleuchtung" der Szene
		  *
		  * @param su     SimpleUniverse
		  */
	  public void addLight(SimpleUniverse su)
	  {

	    BranchGroup bgLight = new BranchGroup();

	    BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0), 1000.0);
	    Color3f lightColour1 = new Color3f(0.5f,0.5f,0.5f);
	    Vector3f lightDir1  = new Vector3f(-1.0f,0.0f,-0.5f);
	    DirectionalLight light1 = new DirectionalLight(lightColour1, lightDir1);
	    light1.setInfluencingBounds(bounds);
	    
	    Vector3f lightDir2  = new Vector3f(1.0f,0.0f,0.5f);
	    DirectionalLight light2 = new DirectionalLight(lightColour1, lightDir2);
	    light2.setInfluencingBounds(bounds);

	    bgLight.addChild(light1);
	    bgLight.addChild(light2);
	    
	    su.addBranchGraph(bgLight);
	  }
}